;;########################################################################
;; regvis7.lsp
;; Visualization for OLS, Robust & Monotonic Regression ViSta model object
;; Contains code for simple regression plot 
;; Copyright (c) 2000 by Forrest W. Young
;;########################################################################

(require "regdemo.lsp")
; ___________________________________________________________________
;
; SIMPLE REGRESSION PLOT
; ___________________________________________________________________

(defun simple-reg-plot (spreadplot-supervisor x y &key (show nil))
  (send simple-reg-plot-proto :new spreadplot-supervisor x y :show show))

(defproto simple-reg-plot-proto 
  '(spreadplot-supervisor showing x dialog)
  '() vista-scatterplot-proto)

(defmeth simple-reg-plot-proto :spreadplot-supervisor (&optional (obj-id nil set)) 
  (when set (setf (slot-value 'spreadplot-supervisor) obj-id)) 
  (slot-value 'spreadplot-supervisor))

(defmeth simple-reg-plot-proto :showing (&optional (obj-id nil set)) 
  (when set (setf (slot-value 'showing) obj-id)) 
  (slot-value 'showing))

(defmeth simple-reg-plot-proto :x (&optional (value nil set)) 
  (when set (setf (slot-value 'x) value)) 
  (slot-value 'x))

(defmeth simple-reg-plot-proto :dialog (&optional (value nil set)) 
  (when set (setf (slot-value 'dialog) value)) 
  (slot-value 'dialog))

(defmeth simple-reg-plot-proto :show-plot ()
  (send self :show-window)
  (send self :showing t))

(defmeth simple-reg-plot-proto :new-y () (send self :change-y-axis))

(defmeth simple-reg-plot-proto :isnew
  (spreadplot-supervisor x y &key (show t))
  (let* ((mod (send spreadplot-supervisor :model))
         (labels (send mod :labels)))
    #+color(when (> *color-mode* 0)
                 (setf color 'blue)
                 (setf line-color 'red) 
                 (send self :use-color t))
    (send self :scale-type nil)
    (send self :spreadplot-supervisor spreadplot-supervisor)
    (setf title "Data with Regression")
    (apply #'call-next-method 
           (combine 2 x y :title "Simple Regression" :show show))
    (send self :add-points x y :point-color 'blue :point-labels labels)
    (send self :mouse-mode 'brushing)
    (send self :adjust-to-data)
    (send self :make-scatterplot-curves)
    (send self :add-regline? t)
    (send self :add-regmeanline? t)
    (send self :redraw-curves)
    ))

#|
(defmeth simple-reg-plot-proto :link-plots (plot-list) 
  (mapcar #'(lambda (plot)
              (send plot :linked t))
          plot-list))


(defmeth simple-reg-plot-proto :make-links (plot-list)      
  (send self :obs-plots plot-list)
  (mapcar #'(lambda (plot)
              (unless (send plot :has-slot 'obs-plots)
                      (send plot :add-slot 'obs-plots)
                      (print plot)
                      (defmeth plot :obs-plots ()
                        (let ((splot (send plot :spreadplot-supervisor)))
                          (when splot (send splot :obs-plots))))
                
                      (defmeth plot :links ()
                        (let ((obs-plots (send plot :obs-plots)))
                          (if (member self obs-plots) obs-plots)))
                
                      (defmeth plot :linked (&optional (link nil set))
                        (let ((obs-plots (send plot :obs-plots)))
                          (when set (setf obs-plots (if link (cons plot obs-plots)
                                                        (remove plot obs-plots)))
                                (call-next-method link))
                          (call-next-method))))
              (send plot :obs-plots plot-list)
              )
          plot-list))
|#

(defmeth simple-reg-plot-proto :simpreg-control-panel (splot msp)
  (send msp :update-residual-plot t)
  (let* ((plot self)
         (add-confidence-lines? nil)
         (x-name (first (send self :variable-labels)))
         (y-name (second (send self :variable-labels)))
         (avp (send msp :added-var-plot))
         (npts (send avp :num-points))
         (x (send avp :point-coordinate 0 (iseq npts)))
         (y (send avp :point-coordinate 1 (iseq npts)))
         (text (send text-item-proto :new  "OPTIONS:"))
         (reg-line    (send toggle-item-proto :new "Regression Line"
                            :value (send plot :add-regline?)
                            :action #'(lambda ()
                                        (send plot :do-simple-regline)
                                        )))
         (resid-lines (send toggle-item-proto :new "Residual Lines"
                            :value (send plot :add-regresiduals?)
                            :action #'(lambda () 
                                        (send plot :do-simple-residlines))))
         (bayes-lines (send toggle-item-proto :new "Confidence Intervals"
                           :value add-confidence-lines?
                           :action #'(lambda ()
                                       (send self :do-bayes-lines msp bayes-lines))))
         (reg-lsmt (send toggle-item-proto :new "Monotone Linearizer"
                         :value (send plot :add-lsmt?)
                         :action #'(lambda () 
                                     (send self :switch-add-lsmt)
                                     )))
         (influ-demo (send toggle-item-proto :new "Influence Points"
                         :action #'(lambda () 
                                     (send self :do-influ-demo
                                           x y x-name y-name)
                                     )))
         (range-demo (send toggle-item-proto :new "Restricted Range"
                         :action #'(lambda () 
                                     (send self :do-range-demo
                                           x y x-name y-name)
                                     )))
         (dialog (send dialog-proto :new
                       (list  (list (list reg-line reg-lsmt) 
                                    (list resid-lines bayes-lines )
                                    (list influ-demo range-demo)))
                       :location '(2000 2000)
                       :show t)))

    (defmeth simple-reg-plot-proto :do-simple-residlines ()
      (send self :switch-add-regresiduals)
      (send resid-lines :value (send plot :add-regresiduals?))
      (when (and (send resid-lines :value)
                 (not (send reg-line :value)))
            (send self :add-regline t)
            (send self :add-regline? t)
            (send reg-line :value t)))

    (defmeth simple-reg-plot-proto :do-simple-regline ()
      (send self :switch-add-regline)
      (send reg-line :value (send self :add-regline?))
      (when (and (not (send self :add-regline?))
                 (send self :add-regresiduals?))
            (send self :add-regresiduals nil)
            (send seld :add-regresiduals? nil)
            (send resid-lines :value nil)))

    (defmeth simple-reg-plot-proto :do-influ-demo (x y x-name y-name )
      (regression-effects-plot x y #'influence-effects-plot 1))

    
    (defmeth simple-reg-plot-proto :do-range-demo (x y x-name y-name )
      (regression-effects-plot x y #'restriction-of-range-plot 0))

    (send dialog :title "Control Panel")
    dialog))
                 
  
(defmeth simple-reg-plot-proto :fix-resids-plot (ssp)
  (send ssp :confidence-intervals nil)
  (send ssp :update-residual-plot)
  )


(defmeth simple-reg-plot-proto :do-bayes-lines (ssp bayes-lines)
    (send ssp :confidence-intervals 
          (not (send ssp :confidence-intervals)))
    (send ssp :update-residual-plot)
    (send bayes-lines :value 
          (send ssp :confidence-intervals)))

(defmeth simple-reg-plot-proto :close ()
  (send (send self :spreadplot-supervisor) :close-dialog self))


(defmeth simple-reg-plot-proto :obs-plots (&optional (obj-list nil arg-used))
  (let ((splot (send self :spreadplot-supervisor)))
    (when splot (if arg-used (send splot :obs-plots obj-list)
                    (send splot :obs-plots)))))
 
#|
(defmeth simple-reg-plot-proto :obs-plots ()
  (let ((splot (send self :spreadplot-supervisor)))
    (when splot (send splot :obs-plots))))
 |#
(defmeth simple-reg-plot-proto :links ()
   (let ((obs-plots (send self :obs-plots)))
     (if (member self obs-plots) obs-plots)))
     
(defmeth simple-reg-plot-proto :linked (&optional (link nil set))
  (let ((obs-plots (send self :obs-plots)))
    (when set (setf obs-plots (if link (cons self obs-plots)
                                  (remove self obs-plots)))
          (call-next-method link))
    (call-next-method)))
